package com.cloud.common.config;

import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheManager.RedisCacheManagerBuilder;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;

import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;

@EnableCaching
@Configuration
public class RedisConfig {
	@Autowired
	private LettuceConnectionFactory lettuceConnectionFactory;
	
	/**
	 * 使用配置文件，结合nacos配置中心，更好管理
	 * @return org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
	
	 @Bean
	 public LettuceConnectionFactory lettuceConnectionFactory() {
		 
//		 	 
//		  RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
//				  .master("mymaster")//连接主节点，将自动从主节点得到从节点信息	
//				  .sentinel("127.0.0.1", 26379)// 连接哨兵
//				  .sentinel("127.0.0.1", 26380);// 连接哨兵
		 
		 
		 //单机连接
		 var lettuceConnectionFactory =new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379));

		 return lettuceConnectionFactory;
	 }
	  */
		@Bean(name = "redisTemplate1")
		public RedisTemplate<String, Object> redisTemplate() {
			
			// 设置序列化
			Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
			ObjectMapper om = new ObjectMapper();
			om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
//			om.enableDefaultTyping(DefaultTyping.NON_FINAL);
			//上一行代码被标记废弃，改为以下可用。（估计是为了安全，网络序列化和反序列化，可能有安全漏洞）
			om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, DefaultTyping.NON_FINAL);
			jackson2JsonRedisSerializer.setObjectMapper(om);
			// 配置redisTemplate
			RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
			redisTemplate.setConnectionFactory(lettuceConnectionFactory);
			RedisSerializer<?> stringSerializer = new StringRedisSerializer();
			redisTemplate.setKeySerializer(stringSerializer);// key序列化
			redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化
			redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化
			redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化
			redisTemplate.afterPropertiesSet();
			return redisTemplate;
		}
	
    @Bean
    public CacheManager cacheManager() {
// 		默认配置1，create方法默认返回return new RedisCacheManager(new DefaultRedisCacheWriter(connectionFactory),RedisCacheConfiguration.defaultCacheConfig());
//    	RedisCacheManager cacheManager = RedisCacheManager.create(lettuceConnectionFactory());
// 		默认配置2，同上
//    	var cacheManager =RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory());
    	
    	var redisCacheConfiguration=RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(15))
    			.serializeKeysWith(SerializationPair.fromSerializer(new StringRedisSerializer()))
    			.serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    	
    	RedisCacheManager cacheManager = RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory).cacheDefaults(redisCacheConfiguration).build();
        return cacheManager;
    }
}
